﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Timers;
using System.Collections;
using Sector7.Framework.Utility;
using System.ComponentModel;
using System.Windows.Controls.Primitives;

namespace Sector7.Restaurant.Controls
{
    /// <summary>
    /// PromptBox.xaml 的交互逻辑
    /// </summary>
    public partial class PromptBox : ComboBox
    {
        #region Members
        /// <summary>
        /// 视图控件集
        /// </summary>
        private VisualCollection _visualControls;

        /// <summary>
        /// 输入框
        /// </summary>
        private TextBox _textBox;

        /// <summary>
        /// 选择框
        /// </summary>
        private ComboBox _comboBox;

        /// <summary>
        /// 输入提示计时器
        /// </summary>
        private Timer _keypressTimer;

        /// <summary>
        /// 是否输入文本
        /// </summary>
        private bool _isInputText;

        /// <summary>
        /// 文本改变回调委托
        /// </summary>
        private delegate void TextChangedCallback();

        /// <summary>
        /// 源对象上某个值的路径，该值作为对象的关键字过滤。
        /// </summary>
        public static DependencyProperty KeywordPathProperty = DependencyProperty.Register("KeywordPath", typeof(string), typeof(PromptBox));

        /// <summary>
        /// 触发输入提示延时
        /// </summary>
        public static DependencyProperty DelayTimeProperty = DependencyProperty.Register("DelayTime", typeof(int), typeof(PromptBox));

        /// <summary>
        /// 触发输入提示字符长度阀值
        /// </summary>
        public static DependencyProperty ThresholdProperty = DependencyProperty.Register("Threshold", typeof(int), typeof(PromptBox));
        #endregion

        #region Constructor
        /// <summary>
        /// 创建输入提示框控件实例
        /// </summary>
        public PromptBox()
        {
            _visualControls = new VisualCollection(this);

            InitializeComponent();

            // set up the key press timer
            _keypressTimer = new Timer();
            _keypressTimer.Elapsed += new ElapsedEventHandler(KeyPressTimer_Elapsed);

            // set up the text box and the combo box
            _comboBox = new ComboBox();
            _comboBox.IsSynchronizedWithCurrentItem = true;
            _comboBox.IsTabStop = false;
            _comboBox.SelectionChanged += new SelectionChangedEventHandler(ComboBox_SelectionChanged);

            _textBox = new TextBox();
            _textBox.TextChanged += new TextChangedEventHandler(TextBox_TextChanged);
            _textBox.VerticalContentAlignment = VerticalAlignment.Center;

            _visualControls.Add(_comboBox);
            _visualControls.Add(_textBox);
        }
        #endregion

        #region Methods
        /// <summary>
        /// 获取或设置源对象上某个值的路径，该值作为对象的关键字过滤。
        /// </summary>
        public string KeywordPath
        {
            get { return base.GetValue(KeywordPathProperty).ToString(); }
            set { base.SetValue(KeywordPathProperty, value); }
        }

        /// <summary>
        /// 获取或设置当前选择中的第一项，或者，如果选择为空，则返回 null。
        /// </summary>
        public new object SelectedItem
        {
            get { return _comboBox.SelectedItem; }
            set { _comboBox.SelectedItem = value; }
        }

        /// <summary>
        /// 获取或设置文本内容。
        /// </summary>
        public new string Text
        {
            get { return _textBox.Text; }
            set 
            {
                _isInputText = true;
                _textBox.Text = value; 
            }
        }

        /// <summary>
        /// 获取或设置触发输入提示延时
        /// </summary>
        public int DelayTime
        {
            get { return (int)base.GetValue(DelayTimeProperty); }
            set { base.SetValue(DelayTimeProperty, value); }
        }

        /// <summary>
        /// 获取或设置触发输入提示字符长度阀值
        /// </summary>
        public int Threshold
        {
            get { return (int)base.GetValue(ThresholdProperty); }
            set { base.SetValue(ThresholdProperty, value); }
        }

        private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            object selectedItem = _comboBox.SelectedItem;
            if (selectedItem != null)
            {
                _isInputText = true;
                _textBox.Text = ReflectionUtil.GetPropertyValue(selectedItem, DisplayMemberPath).ToString();
            }
        }

        /// <summary>
        /// 文本改变处理
        /// </summary>
        private void TextChanged()
        {
            if (!_comboBox.DisplayMemberPath.Equals(this.DisplayMemberPath))
                _comboBox.DisplayMemberPath = this.DisplayMemberPath;

            string text = _textBox.Text;
            _comboBox.Items.Clear();
            if (text.Length >= Threshold)
            {
                foreach (var item in this.ItemsSource)
                {
                    object keyWord = ReflectionUtil.GetPropertyValue(item, KeywordPath);
                    if (keyWord != null && keyWord.ToString().StartsWith(text, StringComparison.CurrentCultureIgnoreCase))
                    {
                        _comboBox.Items.Add(item);
                    }
                }

                _comboBox.IsDropDownOpen = _comboBox.HasItems;
            }
            else
            {
                _comboBox.IsDropDownOpen = false;
            }
        }

        private void KeyPressTimer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _keypressTimer.Stop();
            Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                new TextChangedCallback(this.TextChanged));
        }

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            // text was not typed, do nothing and consume the flag
            if (_isInputText == true)
            {
                _isInputText = false;
            }
            // if the delay time is set, delay handling of text changed
            else
            {
                if (DelayTime > 0)
                {
                    _keypressTimer.Interval = DelayTime;
                    _keypressTimer.Start();
                }
                else
                {
                    TextChanged();
                }
            }
        }

        protected override Size ArrangeOverride(Size arrangeSize)
        {
            _textBox.Arrange(new Rect(arrangeSize));
            _comboBox.Arrange(new Rect(arrangeSize));
            return base.ArrangeOverride(arrangeSize);
        }

        protected override Visual GetVisualChild(int index)
        {
            return _visualControls[index];
        }

        protected override int VisualChildrenCount
        {
            get { return _visualControls.Count; }
        }
        #endregion
    }
}
